package com.tian.intercptor;

import com.alibaba.fastjson.JSON;
import com.tian.dto.ChargeUserLoginResDto;
import com.tian.enums.ResultCode;
import com.tian.exception.BusinessException;
import com.tian.util.RedisConstantPre;
import com.tian.util.StringUtil;
import com.tian.util.UserCacheUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * @author tianwc  公众号：java后端技术全栈、面试专栏
 * @version 1.0.0
 * @date 2022年11月01日 17:24
 * <p>
 * 登陆校验
 */
@Aspect
@Component
@Slf4j
public class LoginCheckAspect {
    @Resource
    private RedissonClient redissonClient;

    /**
     * 这里我们使用注解的形式
     * 当然，我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
     * 切点表达式:   execution(...)
     * 接口请求参数、相应参数、耗时、路径等信息打印
     */
    @Around("@annotation(com.tian.annotation.LoginCheckAnnotation)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取当前请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();

        String authorization = request.getHeader("Authorization");
        if (StringUtil.isBlank(authorization)) {
            throw new BusinessException(ResultCode.UNAUTHORIZED);
        }
        if (authorization.contains("\"")) {
            authorization= authorization.replace("\"", "");
        }

        RBucket<String> bucket = redissonClient.getBucket(RedisConstantPre.TOKEN_PRE + authorization);
        String cache = bucket.get();
        if (StringUtil.isBlank(cache)) {
            throw new BusinessException(ResultCode.UNAUTHORIZED);
        }
        ChargeUserLoginResDto userInfoCache = JSON.parseObject(cache, ChargeUserLoginResDto.class);
        //用户登录信息放到 ThreadLocal 里
        UserCacheUtil.setUser(userInfoCache);
        try {
            // 执行业务逻辑
            return joinPoint.proceed();
        } finally {
            // 清理ThreadLocal中的用户信息
            UserCacheUtil.clearUser();
        }
    }
}
